package me.hetong.aliyun.oss;

import cn.hutool.core.io.FileUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.log.StaticLog;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import me.hetong.tool.TtBase62Tool;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;

/**
 * OSS文件管理
 *
 * @author hetong
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class TtOSS {

    private String accessKeyId;
    private String accessKeySecret;
    private String endPoint;
    private String domain;
    private String bucketName;
    private String path = "olympus";// 系统自动上传的默认放到此目录下(奥林匹斯山,已知在火星上最高的山，也是太阳系最高的山)
    private OSS ossClient;

    public static TtOSS create() {
        return new TtOSS();
    }

    public TtOSS(String accessKeyId, String accessKeySecret, String endPoint, String domain, String bucketName) {
        this.accessKeyId = accessKeyId;
        this.accessKeySecret = accessKeySecret;
        this.endPoint = endPoint;
        this.domain = domain;
        this.bucketName = bucketName;
        this.ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
    }

    /**
     * 上传绝对路径文件
     *
     * @param filePath
     * @return
     */
    public String upload(String filePath) {
        try {
            return upload(new File(filePath));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 上传文件对象
     *
     * @param file
     * @return
     */
    public String upload(File file) {
        try {
            byte[] bytes = FileUtil.readBytes(file);
            String suffix = getSuffix(file.getAbsolutePath());
            return upload(bytes, suffix);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 上传Spring文件
     *
     * @param file
     * @return
     */
    public String upload(MultipartFile file) {
        try {
            byte[] bytes = file.getBytes();
            String suffix = getSuffix(file.getOriginalFilename());
            return upload(bytes, suffix);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 上传字节数组文件
     *
     * @param bytes
     * @param suffix
     * @return
     */
    public String upload(byte[] bytes, String suffix) {
        String objectPath = getObjectPath(bytes, suffix);
        if (getObjectPathIfExist(objectPath)) {
            // 已经上传过的文件不用再传
            return this.domain + objectPath;
        }
        StaticLog.info("OSS-新文件上传:{}", objectPath);
        ossClient.putObject(bucketName, objectPath, new ByteArrayInputStream(bytes));
        StaticLog.info("OSS-上传成功:{}", objectPath);
        return this.domain + objectPath;
    }

    public boolean getObjectPathIfExist(String objectPath) {
        try {
            // 第二个参数为不包含Bucket名称在内的Object完整路径，例如exampleobject.txt
            if (ossClient.doesObjectExist(bucketName, objectPath)) {
                StaticLog.info("OSS-重复文件:{}", objectPath);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private String getObjectPath(byte[] bytes, String suffix) {
        String key = getKey(bytes);
        return path + "/" + key + suffix;
    }

    public String getKey(String filePath) {
        return getKey(new File(filePath));
    }

    public String getKey(File file) {
        return SecureUtil.sha256(file);
    }

    public String getKey(byte[] bytes) {
        String md5 = SecureUtil.md5(new ByteArrayInputStream(bytes));
        return TtBase62Tool.hexToBase62(md5);
    }

    public static String getSuffix(String fileName) {
        int index = fileName.lastIndexOf(".");
        if (index > 0) {
            return fileName.substring(index);
        }
        return "";
    }
}
